import ctypes

import cv2
import numpy as np

from Utils.metric_and_dist import so


class ROIExtractor:
    def __init__(self):
        pass

    def extract(self, palmprint):
        '''
        extract roi by palmprint image
        :param palmprint:
        :return:
        '''
        pass

    def extract_kp(self, palmprint, x0, x2, y0, y2):
        '''
        extract roi by finger key points
        :param palmprint:
        :param x0:
        :param x2:
        :param y0:
        :param y2:
        :return:
        '''
        pass


class ZhangROIExtractor(ROIExtractor):
    def __init__(self):
        self.libROI = so("/home/yjy/VSCodeProjects/palmMatch/build/libzhangROI.so")
        # self.libROI.extractROI.restype = ctypes.c_void_p
        self.libROI.extractROI.argtypes = (ctypes.c_char_p, ctypes.c_char_p)
        self.libROI.extractROI_kp.argtypes = (
            ctypes.c_char_p, ctypes.c_char_p, ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float)
        self.roi_size = 128

    def extract(self, palmprint):
        roi_out = ctypes.create_string_buffer(self.roi_size * self.roi_size)
        img_data = palmprint.reshape((-1,)).tobytes()
        img_data = ctypes.c_char_p(img_data)
        x0, x2, y0, y2 = ctypes.c_float(), ctypes.c_float(), ctypes.c_float(), ctypes.c_float()
        self.libROI.extractROI(img_data, roi_out, ctypes.byref(x0), ctypes.byref(x2), ctypes.byref(y0),
                               ctypes.byref(y2))
        pts = dict({
            'x0': x0.value,
            'x2': x2.value,
            'y0': y0.value,
            'y2': y2.value
        })
        roi = np.frombuffer(roi_out, dtype=np.uint8, count=self.roi_size * self.roi_size)
        return roi.reshape((self.roi_size, self.roi_size)), pts

    def extract_kp(self, palmprint, x0, x2, y0, y2):
        roi_out = ctypes.create_string_buffer(self.roi_size * self.roi_size)
        img_data = palmprint.reshape((-1,)).tobytes()
        img_data = ctypes.c_char_p(img_data)
        self.libROI.extractROI_kp(img_data, roi_out, x0, x2, y0, y2)
        roi = np.frombuffer(roi_out, dtype=np.uint8, count=self.roi_size * self.roi_size)
        return roi.reshape((self.roi_size, self.roi_size))
